import socket
import threading
import struct
from collections import OrderedDict

# 全局锁保证线程安全
print_lock = threading.Lock()
active_clients = 0

class ProtocolError(Exception):
    pass

def configure_socket(sock):
    """配置Socket参数"""
    # 允许立即重用处于TIME_WAIT状态的地址和端口
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 禁用Nagle算法：减少延迟，立即发送小数据包
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    # 设置操作超时时间：防止永久阻塞
    sock.settimeout(30)

def recv_exact(sock, length):
    """可靠接收指定长度数据"""
    data = b''
    while len(data) < length:
        # 循环获取并拼接内容达到指定长度
        packet = sock.recv(length - len(data))
        if not packet:
            raise ConnectionError("客户端断开")
        data += packet
    return data

def handle_client(conn, addr):
    """处理客户端线程"""
    global active_clients
    try:
        with print_lock:
            active_clients += 1
            print(f"[NEW] {addr} | 活跃连接: {active_clients}")

        # 1. 接收初始化报文 (Type=1, N)
        init_data = recv_exact(conn, 6)
        packet_type, N = struct.unpack('!HI', init_data)
        if packet_type != 1:
            raise ProtocolError(f"无效初始化类型: {packet_type}")

        print(f"[CLIENT {addr}] 块数: {N}")

        # 2. 发送同意报文 (Type=2, 1)
        conn.sendall(struct.pack('!HI', 2, 1))

        # 3. 处理所有数据块
        for bkey in range(1, N + 1):
            # 接收请求报文 (Type=3, bkey, length, data)
            header = recv_exact(conn, 10)
            req_type, bkey_recv, length = struct.unpack('!HII', header)
            data = recv_exact(conn, length)

            if req_type != 3 or bkey_recv != bkey:
                raise ProtocolError(f"块 {bkey} 协议错误")

            # 处理数据反转
            reversed_data = data.decode('utf-8')[::-1]

            # 发送响应报文 (Type=4, bkey, length, reversed_data)
            resp_header = struct.pack('!HII', 4, bkey, len(reversed_data))
            conn.sendall(resp_header + reversed_data.encode('utf-8'))

            with print_lock:
                print(f"[CLIENT {addr}] 完成块 {bkey} ({length}B)")

        #等待客户端关闭
        print(f"[CLIENT {addr}] 所有数据已处理，等待客户端关闭...")
        # 等待客户端主动关闭（检测 FIN）
        try:
            data = conn.recv(1)  # 非阻塞检测，或设置超时
            if data:
                raise ProtocolError("客户端未关闭连接")
        except (ConnectionResetError, socket.timeout):
            pass  # 客户端已关闭

        print(f"[CLIENT {addr}] 客户端已主动关闭")


    except Exception as e:
        with print_lock:
            print(f"[ERROR {addr}] {str(e)}")
    finally:
        with print_lock:
            active_clients -= 1
            # 服务器此时被动关闭连接（由客户端触发）
            conn.close()
            print(f"[CLOSE] {addr} | 活跃连接: {active_clients}")


def start_server(host='0.0.0.0', port=3083):
    """启动服务器"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        configure_socket(s)
        s.bind((host, port))
        s.listen(10)
        print(f"[SERVER] 启动于 {host}:{port} | 等待连接...")

        try:
            while True:
                conn, addr = s.accept()
                threading.Thread(
                    target=handle_client,  # 线程函数
                    args=(conn, addr),  # 传递给线程的参数
                    daemon=True  # daemon=True确保主线程可中断
                ).start()
        except KeyboardInterrupt:
            print("\n服务器关闭")


if __name__ == "__main__":
    start_server()